import React, { useState, useEffect } from 'react';
import { Form, Input, Select, Button, message, Flex } from 'antd';
import { DeleteOutlined } from '@ant-design/icons';
import { clone as cloneDeep } from 'ramda';
import { ElementType, FlowVariableType } from '../../config';
import FilterValue from '../filter/FilterValue';
import { getVariableDataType, isDataTypeEqual, isDataTypeMatch } from '../../utils/dataType';
import VariableSelect from '../common/VariableSelect';
import DataTypeDisplay from '../common/DataTypeDisplay';
import useFlowStore from '../../hooks/flowStore';
import styled from 'styled-components';

const { TextArea } = Input;

const assignTypeList = [
  { value: 'CONSTANT', label: '常量' },
  { value: 'VARIABLE', label: '变量' },
];

const columns = [
  { name: '变量名称', prop: 'source' },
  { name: '数据类型', prop: 'sourceDataType' },
  { name: '赋值方式', prop: 'targetType' },
  { name: '赋值', prop: 'target' },
];

const AssignForm = ({ data, onUpdate, onCancel }) => {
  const [form] = Form.useForm();
  const [nodeData, setNodeData] = useState(getDefaultData());
  const flowContext = useFlowStore();

  function getDefaultData() {
    return {
      key: '',
      name: '',
      desc: '',
      outgoings: [],
      incomings: [],
      elementType: ElementType.ASSIGN,
      assignRules: [],
    };
  }

  useEffect(() => {
    if (data) {
      setNodeData(Object.assign(getDefaultData(), cloneDeep(data)));
    }
  }, [data]);

  const targetEnvList = flowContext.data.flowVariables;

  const sourceEnvList = flowContext.data.flowVariables.filter(
    (item) => [FlowVariableType.INPUT, FlowVariableType.TEMP].includes(item.envType)
  );

  const validate = () => {
    if (!nodeData.name) {
      message.error('节点名称不能为空');
      return false;
    }
    return true;
  };

  const onSubmit = () => {
    if (!validate()) {
      return;
    }
    onUpdate(cloneDeep(nodeData));
  };

  const getAvailableTarget = (target) => {
    return targetEnvList.filter((item) => {
      if (item.envKey === target) {
        return item;
      }
      return !nodeData.assignRules.map((item) => item.target).includes(item.envKey);
    });
  };

  const getAvailableSource = (target, targetDataType) => {
    return sourceEnvList.filter((item) => {
      if (item.envKey === target) {
        return false;
      }
      return isDataTypeMatch(item.dataType, targetDataType);
    });
  };

  const onTargetEnvChange = (rowIndex, value) => {
    const target = value;
    const param = targetEnvList.find((item) => item.envKey === target);
    const newAssignRules = [...nodeData.assignRules];
    newAssignRules[rowIndex] = {
      ...newAssignRules[rowIndex],
      source: '',
      sourceDataType: param?.dataType,
      targetDataType: param?.dataType,
    };
    setNodeData({ ...nodeData, assignRules: newAssignRules });
  };

  const onAssignTypeChange = (rowIndex, value) => {
    const newAssignRules = [...nodeData.assignRules];
    newAssignRules[rowIndex] = {
      ...newAssignRules[rowIndex],
      source: '',
      sourceType: value,
    };
    setNodeData({ ...nodeData, assignRules: newAssignRules });
  };

  const onSourceEnvChange = (rowIndex, value) => {
    const target = nodeData.assignRules[rowIndex].target;
    const targetEnv = getVariableDataType(target, targetEnvList);
    const source = value;
    const sourceEnv = getVariableDataType(source, sourceEnvList);
    if (!isDataTypeEqual(targetEnv.dataType, sourceEnv.dataType)) {
      message.error('所选变量的数据类型与目标变量数据类型不匹配');
      const newAssignRules = [...nodeData.assignRules];
      newAssignRules[rowIndex] = {
        ...newAssignRules[rowIndex],
        source: '',
      };
      setNodeData({ ...nodeData, assignRules: newAssignRules });
      return;
    }
    const newAssignRules = [...nodeData.assignRules];
    newAssignRules[rowIndex] = {
      ...newAssignRules[rowIndex],
      sourceDataType: sourceEnv.dataType,
    };
    setNodeData({ ...nodeData, assignRules: newAssignRules });
  };

  const addAssignRule = () => {
    const newAssignRules = nodeData.assignRules || [];
    newAssignRules.push({
      source: '',
      sourceDataType: null,
      sourceType: 'VARIABLE',
      target: '',
      targetDataType: null,
      targetType: 'VARIABLE',
    });
    setNodeData({ ...nodeData, assignRules: newAssignRules });
  };

  const removeRule = (rowIndex) => {
    const newAssignRules = [...nodeData.assignRules];
    newAssignRules.splice(rowIndex, 1);
    setNodeData({ ...nodeData, assignRules: newAssignRules });
  };

  return (
    <div className="node-method-form">
      <Form form={form} layout="vertical">
        <Form.Item label="节点编码">
          <span>{nodeData.key}</span>
        </Form.Item>
        <Form.Item label="节点名称">
          <Input
            value={nodeData.name}
            onChange={(e) => setNodeData({ ...nodeData, name: e.target.value })}
            placeholder="请输入"
          />
        </Form.Item>
        <Form.Item label="节点描述">
          <TextArea
            value={nodeData.desc}
            onChange={(e) => setNodeData({ ...nodeData, desc: e.target.value })}
            placeholder="请输入"
            rows={2}
          />
        </Form.Item>
        <Form.Item label="赋值规则">
          <StylesWrap className="rule-setting">
            <div className="rule-setting-head">
              <div className="rule-setting-tr">
                {columns.map((column) => (
                  <div key={column.prop} className="rule-setting-td">
                    {column.name}
                  </div>
                ))}
                <div className="rule-setting-td delete-td"></div>
              </div>
            </div>
            <div className="rule-setting-body">
              {nodeData.assignRules.map((rule, rowIndex) => (
                <div key={rowIndex} className="rule-setting-tr">
                  {columns.map((column) => (
                    <div key={column.prop} className="rule-setting-td">
                      {column.prop === 'source' && (
                        <Select
                          value={rule.target}
                          popupMatchSelectWidth={false}
                          size="small"
                          onChange={(value) => onTargetEnvChange(rowIndex, value)}
                          style={{ width: '100%' }}
                        >
                          {getAvailableTarget(rule.target).map((item) => (
                            <Select.Option key={item.envKey} value={item.envKey}>
                              <Flex align='center' justify='space-between'>
                                <span >{item.envKey}</span>
                                <span
                                  style={{
                                    color: 'rgba(255, 255, 255, 0.45)',
                                    fontSize: '13px',
                                    marginLeft: '5px',
                                  }}
                                >
                                  {item.envName}
                                </span>
                              </Flex>

                            </Select.Option>
                          ))}
                        </Select>
                      )}
                      {column.prop === 'sourceDataType' && (
                        <DataTypeDisplay dataType={rule.targetDataType} />
                      )}
                      {column.prop === 'targetType' && (
                        <Select
                          value={rule.sourceType}
                          size="small"
                          onChange={(value) => onAssignTypeChange(rowIndex, value)}
                          style={{ width: '100%' }}
                        >
                          {assignTypeList.map((item) => (
                            <Select.Option key={item.value} value={item.value}>
                              {item.label}
                            </Select.Option>
                          ))}
                        </Select>
                      )}
                      {column.prop === 'target' && (
                        <>
                          {rule.sourceType === 'CONSTANT' ? (
                            <FilterValue
                              value={rule.source}
                              onChange={(value) => {
                                const newAssignRules = [...nodeData.assignRules];
                                newAssignRules[rowIndex] = {
                                  ...newAssignRules[rowIndex],
                                  source: value,
                                };
                                setNodeData({ ...nodeData, assignRules: newAssignRules });
                              }}
                              dataType={rule.targetDataType}
                              size="small"
                              showNumberControls={false}
                            />
                          ) : (
                            <VariableSelect
                              value={rule.source}
                              onChange={(value) => onSourceEnvChange(rowIndex, value)}
                              size="small"
                              options={getAvailableSource(rule.target, rule.targetDataType)}
                              filterDataType={rule.targetDataType}
                            />
                          )}
                        </>
                      )}
                    </div>
                  ))}
                  <div className="rule-setting-td delete-td">
                    <DeleteOutlined onClick={() => removeRule(rowIndex)} />
                  </div>
                </div>
              ))}
            </div>
            <div className="rule-setting-foot">
              <Button size="small" type="default" onClick={addAssignRule}>
                新增赋值
              </Button>
            </div>
          </StylesWrap>
        </Form.Item>
        <Form.Item>
          <Button type="primary" onClick={onSubmit}>
            确定
          </Button>
          <Button onClick={onCancel}>取消</Button>
        </Form.Item>
      </Form>
    </div>
  );
};


const StylesWrap = styled.div`
  &.rule-setting {
  width: 100%;
  .rule-setting-head {
    background-color: #002f5c;
    padding: 0 1px;
    color: #9ccdff;
  }
  .rule-setting-body {
    /* border-left: 1px solid #f2f2f2;
    border-right: 1px solid #f2f2f2; */
  }
  .rule-setting-tr {
    display: flex;
    /* border-bottom: 1px solid #f2f2f2; */
    height: 36px;
  }
  .rule-setting-td {
    flex: 1;
    min-width: 0;
    padding: 0 6px;
    display: flex;
    align-items: center;
    .required {
      color: red;
      width: 10px;
    }
    &.delete-td {
      width: 40px;
      flex: none;
      justify-content: center;
    }
    &.delete-td {
      width: 20px;
      margin-right: 10px;
      & > .el-icon {
        cursor: pointer;
        color: #999;
      }
    }
  }
  .rule-setting-foot {
    text-align: center;
    padding: 6px 0;
  }
}

.rule-setting-td{
  .dataTypeName {
    color: var(--el-text-color-regular);
  }
}
`

export default AssignForm; 